﻿// 0720train03.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <unordered_map>
#include <unordered_set>
#include <algorithm>
#include <limits.h>

using namespace std;

/*
 现有两组服务器A和B，每组有多个算力不同的CPU，
 其中Ai是A组第i个CPU的运算能力，Bi是B组第i个CPU的运算能力。
 一组服务器的总算力是各CPU的算力之和。
目标：两组服务器的算力相等，
每组各选出一个CPU进行一次交换，
求两组服务器中，用于交换的CPU的算力，并且要求从A组服务器中选出的CPU，算力尽可能小。

输入
第一行输入为L1和L2，以空格分隔，L1表示A组服务器中的CPU数量，L2表示B组服务器中的CPU数量
第二行输入为A组服务器中各个CPU的算力值，以空格分隔。
第三行输入为B组服务器中各个CPU的算力值，以空格分隔。
1 <= L1 <= 10000
1 <= L2 <= 10000
1 <= A[i] <= 100000
1 <= B[i] <= 100000

输出
对于每组测试数据，输出两个整数，
以空格分隔，依次表示A组选出的CPU算力、B组选出的CPU算力，
要求从A组选出的CPU的算力尽可能小。

输入
2 2
1 1
2 2
输出
1 2

输入
3 4
1 2 3
1 2 3 4
输出
1 3

 */

int GetVecSum(vector<int>oh_vec)
{
    int oh_sum_result = 0;
    for (auto& oh_num : oh_vec)
    {
        oh_sum_result += oh_num;
    }
    return oh_sum_result;
}

int GetNewSum(int origin_sum, int change1, int change2, int type)
{
	//change1 < change2
    if (1==type)
    {
        return origin_sum + (change2 - change1);
    }
    else if (2==type)
    {
        return origin_sum - (change2 - change1);
    }

    return -1;
}


void solve01(vector<int>&vec1, vector<int>& vec2)
{
    //00优先假设a算力更小
    //0先记录两个数组的和，vec1[i]必定小于vec2[j]
    //1遍历vec1, 遍历vec2双层for, vec2[j]置换vec1[i]
    //2找到数组之和相同的数时，记录下数字map[i]=j
    //3遍历map，找出vec1[map_item.first]最小的值

    bool is_change = false;
    unordered_map<int, int>oh_map;

    int sum_vec1 = GetVecSum(vec1);
    int sum_vec2 = GetVecSum(vec2);
    vector<int>oh_vec1 ;
    vector<int>oh_vec2 ;
    if (sum_vec1<=sum_vec2)
    {
        oh_vec1 = vec1;
        oh_vec2 = vec2;
    }
    else
    {
        oh_vec1 = vec2;
        oh_vec2 = vec1;
        is_change = true;

        int tmp = sum_vec2;
        sum_vec2 = sum_vec1;
        sum_vec1 = tmp;
    }

    int vec1_size = oh_vec1.size();
    int vec2_size = oh_vec2.size();

    for (int i1=0; i1< vec1_size;i1++)
    {
        int tmp_sum1;
        int tmp_sum2;
	    for (int j2=0; j2<vec2_size;j2++)
	    {
            int curr_num1 = oh_vec1[i1];
            int curr_num2 = oh_vec2[j2];

            tmp_sum1 = GetNewSum(sum_vec1, curr_num1, curr_num2, 1);
            tmp_sum2 = GetNewSum(sum_vec2, curr_num1, curr_num2, 2);

            if (tmp_sum1==tmp_sum2)
            {
                oh_map[curr_num1] = curr_num2;

                //cout << "map curr_num1" << curr_num1 << " curr_num2 " << curr_num2 << endl;
            }

	    	//j2
        //for------
	    }

        //for------
    }

    int real_num2;
    int res_num1 = INT_MAX;
    for (auto&map_item:oh_map)
    {
        if (!is_change)
        {
            int curr_num1 = map_item.first;
            res_num1 = min(curr_num1, res_num1);
        }
        else
        {
            //res_num1真正的1
            int curr_num1 = map_item.second;
            if (curr_num1<res_num1)
            {
                res_num1 = curr_num1;
                real_num2 = map_item.first;
            }
        }
        
    }

    if (!is_change)
    {
        cout << res_num1 << ' ' << oh_map[res_num1];
    }
	else
    {
        cout << res_num1 << ' ' << real_num2;
    }
    

    //solve01
    //-------
}


/*
 数组，计算最大N个数与最小N个数的和。对数组进行去重

输入
第一行输入M， M标识数组大小
第二行输入M个数，标识数组内容
第三行输入N，N表达需要计算的最大、最小N个数

输出
输出最大N个数与最小N个数的和。

数组中数字范围[0，1000]
最大N个数与最小N个数不能有重叠，如有重叠返回-1

输入
5
95 88 83 64 100
2
输出
342

 */
void solve02(vector<int>&vec_1, int range)
{
    unordered_set<int>oh_set;
    vector<int>oh_vec;

    for (auto &num:vec_1)
    {
	    if (!oh_set.count(num))
	    {
            oh_vec.push_back(num);
            oh_set.insert(num);
	    }
    }

    if (oh_vec.size() < (2 * range))
    {
        cout << -1;
        return;
    }

    sort(oh_vec.begin(), oh_vec.end());

    //for (auto&item:oh_vec)
    //{
    //    cout << item << ' ';
    //}

    int result = 0;
    for (int i=0; i<range;i++)
    {
        result += oh_vec[i];
    }
    int oh_vec_size = oh_vec.size();
    int max_num_begin = oh_vec_size - range;
    for (int i= max_num_begin; i<oh_vec_size;i++)
    {
        result += oh_vec[i];
    }

    cout << result;

    //solve02
    //------
}


/*
规则
words 的字符仅由 a-z 英文小写字母组成
chars 由 a-z 英文小写字母和 “?” 组成。其中英文问号 “?” 表示万能字符
?替代任意一个
chars 每个字母,万能字符 1次

chars 中的字母拼写出 words

输入
第 1 行输入数组 words 的个数，记为 N。
从第 2 行开始到第 N+1 行一次输入数组 words 的每个字符串元素。
第 N+2 行输入字符串 chars

输出
输出一个整数，chars可以拼出几个words

输入
4
cat
bt
hat
tree
atach

输出
2

 */

bool CheckStrVerify(string oh_string, unordered_map<char, int>oh_map)
{
    bool is_verify = true;
    int solu_count = 0;
    if (oh_map.count('?'))
    {
        solu_count = oh_map['?'];
    }

    for (auto& oh_char : oh_string)
    {
        if (!oh_map[oh_char])
        {
            if (solu_count==0)
            {
                is_verify = false;
            }
        	else
            {
                solu_count--;
            }
        }
        else
        {
            int char_count = oh_map[oh_char];
            if (char_count==0)
            {
                is_verify = false;
            }
        	else
            {
                oh_map[oh_char] -= 1;
            }

        }
    }
    return is_verify;
    //CheckStrVerify
}

void solve03(vector<string>vec_str, string oh_string)
{
    unordered_map<char, int>oh_map;

    for (auto&oh_char:oh_string)
    {
	    if (oh_map.count(oh_char))
	    {
            oh_map[oh_char] += 1;
	    }
        else
        {
            oh_map[oh_char] = 1;
        }
    }

    int result = 0;
    for (int i=0; i<vec_str.size();i++)
    {
        string curr_str = vec_str[i];
        
        bool is_verify = CheckStrVerify(curr_str, oh_map);
        if (is_verify)
        {
            result += 1;
        }

        //for-----
        //--------
    }
    cout << result;
    //solve03
    //------
}


/*
 规则
 访问次数大于等于设定阈值，则认为是热内存页，否则是冷内存页。
 
 输入
 第一行为输入为N，表示访存序列的记录条数，0 < N < 10000。
第二行为访存序列，空格间隔的N个内存页框号，页框号范围0-65535，
同一页框号可能重复出现，出现的次数即为对应页框号的频次。
第三行为热内存页的频次阈值T，正整数，范围1 < T < 10000

输出
第一行输出标记为热内存的内存页个数，如果没有被标记为热内存的，则输出0。
如果第一行>0，则接下来按照访问频次降序输出内存页框号，一行一个，频次一样的页框号，页框号小的排前面。

输入
10
1 2 1 2 1 2 1 2 1 2
5

输出
2
1
2

内存页1和内存页2均被访问了5次，达到了阈值5，
因此热内存页有2个。
内存页1和内存页2的访问频次相等，页框号小的排前面。

 */
struct NumNode
{
    int value, count;

    NumNode() = default;
    NumNode(int value, int count) :value(value), count(count) {};
};

bool Compare04(NumNode &node1, NumNode& node2)
{
	if (node1.count == node2.count)
	{
        return node1.value < node2.value;
	}
    return node1.count > node2.count;
}

void solve04(vector<int>&vec_1, int limit)
{
    unordered_map<int, int>oh_map;

    for (auto&oh_num:vec_1)
    {
	    if (!oh_map.count(oh_num))
	    {
            oh_map[oh_num] = 1;
	    }
    	else
    	{
            oh_map[oh_num] += 1;
    	}
    }

    vector<NumNode>result_vec;
    for (auto &map_item:oh_map)
    {
        int num_count = map_item.second;
        int num = map_item.first;

        
        if (num_count>=limit)
        {
            NumNode node(num, num_count);
            result_vec.push_back(node);
        }
        
    }
    
    

    if (result_vec.empty())
    {
        cout << 0;
        return;
    }
    cout << result_vec.size() << endl;

    sort(result_vec.begin(), result_vec.end(), Compare04);
    for (auto&node:result_vec)
    {
        cout << node.value << endl;
    }
    
    //solve04
    //------
}



int main()
{

	{
        int total_count;
        cin >> total_count;
        vector<int>vec_1(total_count);
        for (int i=0; i<total_count;i++)
        {
            cin >> vec_1[i];
        }
        int limit;
        cin >> limit;

        //for (auto&item:vec_1)
        //{
        //    cout << item << ' ';
        //}

        //11
        //    1 2 1 2 1 2 1 2 1 2 2
        //    5
        //vector<int>vec_1 = { 1,2,1,2,1,2,1,2,1,2 };
        //int limit = 5;

        solve04(vec_1, limit);
        return 0;
	}

	{
        int total_size;
        cin >> total_size;
        vector<string>vec_str(total_size);

        for (int i=0; i<total_size;i++)
        {
            cin >> vec_str[i];
        }
        string oh_string;
        cin >> oh_string;

        //for (auto&str:vec_str)
        //{
        //    cout << str << ' ';
        //}

        //cat
        //bt
        //hat
        //tree
        //atach
        //vector<string>vec_str = {"cat","bt","hat","tree"};
        //string oh_string = "atach";
        solve03(vec_str, oh_string);

        return 0;
	}

	{
        string oh_string = "caa";
        unordered_map<char, int>oh_map = { {'c',1},{'a',1},{'?',1} };

        cout << CheckStrVerify(oh_string, oh_map);

        return 0;
	}

	{
        int total_size;
        cin >> total_size;

        vector<int>vec_1(total_size);
        for (int i=0; i<total_size;i++)
        {
            cin >> vec_1[i];
        }

        int range;
        cin >> range;

        //for (auto &num:vec_1)
        //{
        //    cout << num;
        //}

        //5 95 88 83 64 100 2
        //342
        //int range = 2;
        //vector<int>vec_1 = { 95,88,83,64,100 };
        solve02(vec_1, range);
        return 0;
	}

/*
输入
2 2
1 1
2 2
输出
1 2

输入
3 4
1 2 3
1 2 3 4
输出
1 3
     */
    int count1, count2;
    cin >> count1 >> count2;
    vector<int>vec1(count1);
    vector<int>vec2(count2);
    for (int i1=0; i1<count1; i1++)
    {
        cin >> vec1[i1];
    }

    for (int i2 = 0; i2 < count2; i2++)
    {
        cin >> vec2[i2];
    }
    //for (auto& i2 : vec2)
    //{
    //    cout << i2;
    //}
    

    //vector<int>vec1 = { 1, 1 };
    //vector<int>vec2 = { 2, 2 };
    solve01(vec1, vec2);
}

// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单

// 入门使用技巧: 
//   1. 使用解决方案资源管理器窗口添加/管理文件
//   2. 使用团队资源管理器窗口连接到源代码管理
//   3. 使用输出窗口查看生成输出和其他消息
//   4. 使用错误列表窗口查看错误
//   5. 转到“项目”>“添加新项”以创建新的代码文件，或转到“项目”>“添加现有项”以将现有代码文件添加到项目
//   6. 将来，若要再次打开此项目，请转到“文件”>“打开”>“项目”并选择 .sln 文件
